package com.yifeng.repo.micro.service.server.engine.listener;

import com.gomcarter.frameworks.base.common.RequestUtils;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.yifeng.repo.base.utils.common.BaseUtil;
import com.yifeng.repo.micro.service.server.engine.manager.RequestBodyManager;
import com.yifeng.repo.micro.service.server.engine.manager.RequestHeaderManager;
import org.slf4j.MDC;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.List;

import static com.yifeng.repo.micro.service.server.engine.manager.RequestHeaderManager.*;

/**
 * Created by daibing on 2023/3/27.
 */
public class AppRequestListener implements ServletRequestListener {
    private final List<String> copyHeaderPrefixList;

    public AppRequestListener() {
        this.copyHeaderPrefixList = Lists.newArrayList("x-");
    }

    public AppRequestListener(List<String> copyHeaderPrefixList) {
        this.copyHeaderPrefixList = copyHeaderPrefixList;
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        RequestHeaderManager.set(REQ_METHOD, request.getMethod());
        RequestHeaderManager.set(REQ_URL, request.getRequestURL().toString());
        RequestHeaderManager.set(REQ_URI, request.getRequestURI());
        RequestHeaderManager.set(REQ_CONTENT_TYPE, request.getContentType());
        RequestHeaderManager.set(REQ_IP, RequestUtils.getRemoteAddress(request));
        RequestHeaderManager.set(REQ_HOST, RequestUtils.getRemoteHost(request));
        RequestHeaderManager.set(BaseUtil.TRACE_ID, BaseUtil.getSkywalkingTraceId());
        this.copyBizRequestHeader(request, copyHeaderPrefixList);

        // 将traceId和frontendId写入MDC支持业务使用，尤其是frontendId支持日志模块获取写入日志中心
        MDC.put(BaseUtil.TRACE_ID, RequestHeaderManager.get(BaseUtil.TRACE_ID));
        MDC.put(BaseUtil.FRONTEND_ID, RequestHeaderManager.get(BaseUtil.FRONTEND_ID));
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        RequestBodyManager.clear();
        RequestHeaderManager.clear();
        MDC.clear();
    }

    protected void copyBizRequestHeader(HttpServletRequest request, List<String> copyHeaderPrefixList) {
        Enumeration<String> hns = request.getHeaderNames();
        if (hns == null || !hns.hasMoreElements()) {
            return;
        }

        while (hns.hasMoreElements()) {
            String name = hns.nextElement();
            if (Strings.isNullOrEmpty(name)) {
                continue;
            }

            String head = name.trim().toLowerCase();
            if (!this.matchHeaderPrefix(head, copyHeaderPrefixList)) {
                continue;
            }

            String value = request.getHeader(name);
            if (Strings.isNullOrEmpty(value)) {
                continue;
            }

            RequestHeaderManager.set(name.trim(), value.trim());
        }
    }

    private boolean matchHeaderPrefix(String head, List<String> copyHeaderPrefixList) {
        for (String headerPrefix : copyHeaderPrefixList) {
            if (head.startsWith(headerPrefix)) {
                return true;
            }
        }
        return false;
    }
}
